﻿
/***************************************************************************

Copyright (c) BizRulX. All rights reserved.

***************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;

namespace RuleXSoft.FrameworkLib
{
    public class ValidationAttributes<T>
    {
        private T _sourceObj;
        
        

        public ValidationAttributes(T itemObj)
        {
            if (itemObj!=null)
            {
                _sourceObj = itemObj; 
            }
        }

        public ValidationAttributes()
        {
            
        }

        public override bool Equals(object obj)
        {
            bool _returnFlag = false;

            if ((obj == null) || (GetType() != obj.GetType()))
                return false;
            T _issueParamObj = (T)obj;

            Type _oType = typeof(T);
            PropertyInfo[] propInfos = _oType.GetProperties();

            PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo property in properties)
            {
                object[] customAtt = property.GetCustomAttributes(typeof(ValidationAttribute), true);
                foreach (System.Attribute attr in customAtt)
                {
                    //if (attr is DirectionAttribute)
                    //{
                    //property - xml rule file value
                    //propInfo - passed param object value
                    DirectionAttribute dirAtt = attr as DirectionAttribute;
                    if (dirAtt == null) continue;

                    //if (!dirAtt.Output)
                    //{
                    //    _returnFlag = true;
                    //}

                    if (!dirAtt.Output)
                    {
                        foreach (PropertyInfo propInfo in propInfos)
                        {
                            if (Convert.ToString(property.Name).Equals(Convert.ToString(propInfo.Name)))
                            {
                                if (property.GetValue(obj, null) != null)
                                {
                                    if (property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith(">")
                                        || property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("<")
                                        || property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith(">=")
                                        || property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("<=")
                                        || property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("=")
                                        || property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("!")
                                        || property.GetValue(obj, null).ToString().Trim().ToUpper().Contains('&'))
                                    {
                                        string strEntireNumberVal = string.Empty;
                                        string strRulXNumberVal = string.Empty;
                                        string strParamObjectNumberVal = string.Empty;
                                        strParamObjectNumberVal = propInfo.GetValue(this, null).ToString();
                                        strEntireNumberVal = property.GetValue(obj, null).ToString();

                                        if (property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith(">="))
                                        {
                                            strRulXNumberVal = strEntireNumberVal.Substring(2).Trim();
                                            if (!string.IsNullOrEmpty(strParamObjectNumberVal))
                                            {
                                                if (Convert.ToInt32(strParamObjectNumberVal) >= Convert.ToInt32(strRulXNumberVal))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                } 
                                            }
                                        }
                                        else if (property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("<="))
                                        {
                                            strRulXNumberVal = strEntireNumberVal.Substring(2).Trim();
                                            if (!string.IsNullOrEmpty(strParamObjectNumberVal))
                                            {
                                                if (Convert.ToInt32(strParamObjectNumberVal) <= Convert.ToInt32(strRulXNumberVal))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                } 
                                            }
                                        }
                                        else if (property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith(">"))
                                        {
                                            strRulXNumberVal = strEntireNumberVal.Substring(1).Trim();
                                            if (!string.IsNullOrEmpty(strParamObjectNumberVal))
                                            {
                                                if (Convert.ToInt32(strParamObjectNumberVal) > Convert.ToInt32(strRulXNumberVal))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                } 
                                            }
                                        }
                                        else if (property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("<"))
                                        {
                                            strRulXNumberVal = strEntireNumberVal.Substring(1).Trim();
                                            if (!string.IsNullOrEmpty(strParamObjectNumberVal))
                                            {
                                                if (Convert.ToInt32(strParamObjectNumberVal) < Convert.ToInt32(strRulXNumberVal))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                } 
                                            }
                                        }
                                        else if (property.GetValue(obj, null).ToString().Trim().ToUpper().StartsWith("!"))
                                        {
                                            strRulXNumberVal = strEntireNumberVal.Substring(1).Trim();
                                            if (!string.IsNullOrEmpty(strParamObjectNumberVal))
                                            {
                                                if (Convert.ToInt32(strParamObjectNumberVal) != Convert.ToInt32(strRulXNumberVal))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                } 
                                            }
                                        }
                                        else if (property.GetValue(obj, null).ToString().Trim().ToUpper().Contains('&'))
                                        {
                                            IList<string> listBetweenNumbers = strEntireNumberVal.Split('&');

                                            int iFirstBetweenNumber = Convert.ToInt32(listBetweenNumbers[0].Trim());
                                            int iSecondBetweenNumber = Convert.ToInt32(listBetweenNumbers[1].Trim());


                                            if (!string.IsNullOrEmpty(strParamObjectNumberVal))
                                            {
                                                if (Convert.ToInt32(strParamObjectNumberVal) > iFirstBetweenNumber
                                                                                        && Convert.ToInt32(strParamObjectNumberVal) < iSecondBetweenNumber)
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                } 
                                            }
                                        }
                                        else
                                        {
                                            _returnFlag = false;
                                            return false;
                                        }
                                    }
                                    else
                                    {
                                        if (property.PropertyType.ToString().Equals("System.Collections.Generic.List`1[System.Object]"))
                                        {
                                            var objRuleXPropVal = string.Empty;

                                            if (IsNumeric(((List<object>)property.GetValue(obj, null))[0].ToString()))
                                            {
                                                if (((List<object>)propInfo.GetValue(this, null)).Contains(Convert.ToInt32(((List<object>)property.GetValue(obj, null))[0])))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                    //break;
                                                }
                                            }
                                            else if (IsDouble(((List<object>)property.GetValue(obj, null))[0].ToString()))
                                            {
                                                if (((List<object>)propInfo.GetValue(this, null)).Contains(Convert.ToDouble(((List<object>)property.GetValue(obj, null))[0])))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                    //break;
                                                }
                                            }
                                            else
                                            {
                                                if (((List<object>)propInfo.GetValue(this, null)).Contains(Convert.ToString(((List<object>)property.GetValue(obj, null))[0])))
                                                {
                                                    _returnFlag = true;
                                                }
                                                else
                                                {
                                                    _returnFlag = false;
                                                    return false;
                                                    //break;
                                                }
                                            }


                                        }
                                        else
                                        {
                                            if (property.GetValue(obj, null).Equals(propInfo.GetValue(this, null)))
                                            {
                                                _returnFlag = true;
                                            }
                                            else
                                            {
                                                _returnFlag = false;
                                                return false;
                                                //break;
                                            }
                                        }

                                        //if (property.GetValue(obj, null).Equals(propInfo.GetValue(this, null)))
                                        //{
                                        //    _returnFlag = true;
                                        //}
                                        //else
                                        //{
                                        //    _returnFlag = false;
                                        //    return false;
                                        //    //break;
                                        //}
                                    }
                                }

                            }
                        }
                    }
                }



            }

            return _returnFlag;
        }

        private bool IsNumeric(string strVal)
        {
            // Return true if this is a number.
            int iNumber;
            double dNumber;
            return (int.TryParse(strVal, out iNumber) || double.TryParse(strVal, out dNumber));

        }

        private bool IsBoolean(string strVal)
        {
            // Return true if this is a number.
            bool bVal;

            return bool.TryParse(strVal, out bVal);

        }
        private bool IsDouble(string strVal)
        {
            // Return true if this is a number.
            double bVal;

            return double.TryParse(strVal, out bVal);

        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
}
